/***************************************************************************
 *   File FilterDFT.cpp		author belot nicolas (karrakis)            *
 *   define FilterDFT
 *   Apply a filter via a DFT		                                   *
 ***************************************************************************
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "FilterDFT.h"
#include <string.h>
namespace libtrckr {

string FilterDFT::HowToTune(){
	return "unset";
}

FilterDFT::FilterDFT(){
	fft=FFT();
}

FilterDFT::FilterDFT(double* re,double* im,int size):DFT(re,im,size){
	fft=FFT(size);
	
}

FilterDFT::FilterDFT(const DFT& d):DFT(d){
	fft=FFT(d.getSize());
}
FilterDFT::FilterDFT(const FilterDFT& f):DFT(f){
	fft=f.fft;
}

FilterDFT::~FilterDFT(){

}

double* FilterDFT::Preview(double* data,int size){
	if(fft.Size()==0 || fft.Size()!=size){
		//We need to recreate a FFT
		fft = FFT(size);
	}
	fft.setIn(data);
	
	DFT d=fft.execute();
	d *= (*this);
	
	fft.setIn(d);
	d = fft.inverse();
	/*double* res = d.getRealParts();
	memcpy(data,res, sizeof(double)*size);
	free(res);*/
	d.getRealParts(data,size);
	for(uint i=0;i<size;i++){
		data[i]/=size;
	}
	return data;
}
Buffer& FilterDFT::Preview(Buffer& b){//preview == execution  ?
	if(fft.Size()==0 || fft.Size()!=b.size()){
		fft = FFT(b.size());
	}
	fft.setIn(b);
	
	DFT d = fft.execute();
	//Applying dft;
	d *= (*this);
	fft.setIn(d);
	d = fft.inverse();
	/*b.flush();
	b.append(d.getRealParts(),d.getSize());*/
	d.getRealParts(b);
	// FFT scale by N
	for(uint i=0;i<b.size();i++){
		b[i]/=b.size();
	}
	return b;
}
void FilterDFT::Init( ){}

void FilterDFT::Tune(DynArray<int>){}

double* FilterDFT::Execution(double *data,int size){
	return Preview(data,size);
}
Buffer& FilterDFT::Execution(Buffer& b){
	return Preview(b);
}
}
